package me.nibo.webframework.commons;

import me.nibo.webframework.commons.enumeration.FieldType;
import me.nibo.webframework.commons.enumeration.ValueEnum;
import me.nibo.webframework.service.account.AuthorizationRealm;
import me.nibo.webframework.service.account.NavAuthorizationInfo;
import me.nibo.webframework.service.account.UnautherizedException;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 变量工具类，该类封装对系统变量的一些静态获取方法
 *
 */
@Component
@SuppressWarnings({"unchecked", "UnusedDeclaration"})
public class VariableUtils {

    /**
     * 默认字典值的值名称
     */
    public static final String DEFAULT_VALUE_NAME = "value";
    /**
     * 默认字典值的键名称
     */
    public static final String DEFAULT_KEY_NAME = "key";


    /**
     * 通过{@link me.nibo.webframework.commons.enumeration.ValueEnum} 接口子类 class 获取数据字典集合
     *
     * @param enumClass 枚举 class
     * @param ignore    要忽略的值
     * @return key value 数据字典 Map 集合
     */
    public static List<Map<String, Object>> get(Class<? extends Enum<? extends ValueEnum<?, ?>>>
                                                        enumClass, Object... ignore) {

        List<Map<String, Object>> result = new ArrayList<>();
        Enum<? extends ValueEnum<?, ?>>[] values = enumClass.getEnumConstants();

        for (Enum<? extends ValueEnum<?, ?>> o : values) {
            ValueEnum<?, ?> ve = (ValueEnum<?, ?>) o;
            Object value = ve.getValue();

            if (!ArrayUtils.contains(ignore, value)) {
                Map<String, Object> dictionary = new HashMap<>();

                dictionary.put(DEFAULT_VALUE_NAME, value);
                dictionary.put(DEFAULT_KEY_NAME, ve.getName());

                result.add(dictionary);
            }

        }

        return result;
    }

    /**
     * 将值转换为对应的类型
     *
     * @param value 值
     * @return 转换好的值
     */
    public static <T> T cast(Object value) {
        return value == null ? null : (T) value;
    }

    /**
     * 将值转换为对应的类型
     *
     * @param value     值
     * @param typeClass 类型 Class
     * @return 转换好的值
     */
    public static <T> T cast(Object value, Class<T> typeClass) {
        return (T) (value == null ? null : ConvertUtils.convert(value, typeClass));
    }

    /**
     * 将 String 类型的值转换为对应的类型
     *
     * @param value     值
     * @param className 类名称,参考{@link me.nibo.webframework.commons.enumeration.FieldType}
     * @return 转换好的值
     */
    public static <T> T cast(String value, String className) {
        Class<?> type = FieldType.getClass(className);
        return (T) cast(value, type);
    }

    /**
     * 获取当事人
     *
     * @return 用户实体 Map
     */
    public static Map<String, Object> getPrincipal() {

        Subject subject = SecurityUtils.getSubject();
        Object principal = subject.getPrincipal();

        if (principal == null) {
            throw new UnautherizedException("不存在当前用户");
        }

        return VariableUtils.cast(principal);
    }

    /**
     * 获取已认证的当事人
     *
     * @return 用户实体 Map
     */
    public static Map<String, Object> getAuthenticatedPrincipal() {
        Subject subject = SecurityUtils.getSubject();
        if (!subject.isAuthenticated()) {
            throw new UnautherizedException("用户未经过认证");
        }

        return VariableUtils.cast(subject.getPrincipal());
    }

    /**
     * 获取记住我当事人
     *
     * @return 用户实体 Map
     */
    public static Map<String, Object> getRememberedPrincipal() {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isRemembered()) {
            Object principal = subject.getPrincipal();
            return VariableUtils.cast(principal == null ? null : principal);
        }

        return null;

    }

    /**
     * 获取当事人首页导航
     *
     * @return 导航集合
     */
    public static List<Map<String, Object>> getPrincipalNavs() {

        DefaultWebSecurityManager webSecurityManager =
                (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
        Collection<Realm> realms = webSecurityManager.getRealms();
        Subject subject = SecurityUtils.getSubject();

        List<Map<String, Object>> navs = new ArrayList<>();

        for (Realm realm : realms) {
            // 只要是 AuthorizationRealm 类。就会存在 getAuthorizationInfo 方法，
            if (realm instanceof AuthorizationRealm) {
                AuthorizationRealm authorizationRealm = (AuthorizationRealm) realm;
                AuthorizationInfo authorizationInfo = authorizationRealm
                        .getAuthorizationInfo(subject.getPrincipals());
                NavAuthorizationInfo navAuthorizationInfo = (NavAuthorizationInfo) authorizationInfo;
                navs.addAll(navAuthorizationInfo.getNavs());
            }
        }

        return navs;
    }
}
